package cm.tl.pms.sys.satoken;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.annotation.SaMode;
import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author laker
 */
public class EasySaInterceprot extends SaInterceptor implements HandlerInterceptor {

    /**
     * 创建一个 Sa-Token 综合拦截器，默认带有注解鉴权能力
     */
    public EasySaInterceprot() {
    }

    /**
     * 创建一个 Sa-Token 综合拦截器，默认带有注解鉴权能力
     *
     * @param auth 认证函数，每次请求执行
     */
    public EasySaInterceprot(SaParamFunction<Object> auth) {
        this.auth = auth;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        // 检查是否标注了 @SaIgnore 注解
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            SaIgnore ignoreAnnotation = handlerMethod.getMethodAnnotation(SaIgnore.class);
            if (ignoreAnnotation != null) {
                // 存在 @SaIgnore 注解，直接放行
                return true;
            }

            // 检查是否标注了 @SaCheckPermission 注解
            SaCheckPermission annotation = handlerMethod.getMethodAnnotation(SaCheckPermission.class);
            if (annotation != null) {
                // 获取注解属性
                String type = annotation.type();
                String[] permissions = annotation.value();
                SaMode mode = annotation.mode();
                String[] orRoles = annotation.orRole();

                // 进行权限检查
                if (!checkPermissions(type, permissions, mode, orRoles)) {
                    // 权限校验失败，返回403
                    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    return false;
                }
            }
        }

        // 调用父类的 preHandle 方法
        return super.preHandle(request, response, handler);
    }

    private boolean checkPermissions(String type, String[] permissions, SaMode mode, String[] orRoles) {
        // 根据注解属性进行权限检查
        if (permissions.length > 0) {
            switch (mode) {
                case AND:
                    for (String permission : permissions) {
                        if (!StpUtil.hasPermission(permission)) {
                            return false;
                        }
                    }
                    break;
                case OR:
                    for (String permission : permissions) {
                        if (StpUtil.hasPermission(permission)) {
                            return true;
                        }
                    }
                    return false;
            }
        }

        if (orRoles.length > 0) {
            for (String role : orRoles) {
                if (StpUtil.hasRole(role)) {
                    return true;
                }
            }
            return false;
        }

        return true;
    }
}
